﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using General.Core.Common;
using General.Core.Data;
using General.Core.UnitOfWork;
using General.Entities;
using General.Entities.Students;
using General.Framework;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace General.Mvc.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    //[Authorize]
    public class ApiController : Controller
    {
        private readonly GeneralDbContext dbContext;
        private readonly IRepository<Students> studentsRepository;
        private readonly IUnitOfWork unitOfWork;

        public ApiController(GeneralDbContext dbContext, IRepository<Students> studentsRepository, IUnitOfWork unitOfWork)
        {
            this.dbContext = dbContext;
            this.studentsRepository = studentsRepository;
            this.unitOfWork = unitOfWork;
        }


        [HttpGet][HttpPost]
        public IActionResult insertTest()
        {
            studentsRepository.insert(new Students() { name="new", pwd="1232" });

            studentsRepository.insert(new Students() { name = "new", pwd = "1232" });
            studentsRepository.insert(new Students() { name = "new", pwd = "1232" });
            unitOfWork.Commit();
            return Ok("添加成功!!!");

        }




        /// <summary>
        /// 测试查询
        /// </summary>
        /// <returns></returns>
        [HttpGet] [HttpPost]
        public IActionResult selectTest()
        {
            var select = from s in dbContext.Students
                         join b in dbContext.settings on s.id equals b.value
                         where s.id == 1
                         select b;

            return Ok(select.ToList());
        }



        /// <summary>
        /// redis队列测试
        /// </summary>
        /// <returns></returns>
        [HttpGet] [HttpPost] 
        public async Task<IActionResult> redisTest() 
        {
            //RedisHelper.LPush("")  //插入值到头部
            //RedisHelper.RPop("")  //从尾部取值

            var result = await HttpHelper.HttpPostAsync("http://www.baidu.com/api/getuserinfo", "userid=23456798");
            return Ok("");
        }


        /// <summary>
        /// 测试方法
        /// </summary>
        /// <returns></returns>
        /// [TypeFilter(typeof(LoginCheckFilterAttribute))]  进行验证 cookie ....
        [HttpGet][HttpPost]
        public IActionResult test() 
        {
            //自带权限验证cookie
            if (this.User.Identity.IsAuthenticated)
            {
                //return RedirectPermanent("");
                return Ok("login!!");
            }
            //记录cookie
            //var mycookieVal = GetCookieValue("userLoginId");
            //使用redis
            //var redisVal = RedisHelper.Get(mycookieVal);

            //return Ok("我的cookie:"+mycookieVal+",redis="+ redisVal);

            return Ok("no login");
        }

        /// <summary>
        /// 测试获取数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [HttpPost]
        [Authorize(AuthenticationSchemes = "Cookies")]
        public IActionResult get()
        {
            return Ok("ok");
        }

        /// <summary>
        /// 测试获取数据
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [HttpPost]
        [Authorize(AuthenticationSchemes = "Bearer")] //jwt验证
        public IActionResult get2()
        {
            var auth = HttpContext.AuthenticateAsync();
            var username = auth.Result.Principal.Claims.First(x=>x.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
            return Ok("ok");
        }

        /// <summary>
        /// 登录jwt
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult loginjwt()
        {
            var claim = new Claim[] {
                    new Claim(ClaimTypes.NameIdentifier, "冰河洗剑"),
                    new Claim("role","admin")
                };

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSettings.SecretKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //第一种方式
            var token = new JwtSecurityToken(
                JwtSettings.Issuer,// Issuer 颁发者，通常为STS服务器地址
                JwtSettings.Audience,// Audience Token的作用对象，也就是被访问的资源服务器授权标识
                claim,
                DateTime.Now,  //Token生效时间，在此之前不可用
                DateTime.Now.AddMinutes(30), //Token过期时间，在此之后不可用
                creds);

            //第二种方式
            //var descriptor = new SecurityTokenDescriptor
            //{
            //    Issuer = _jwtSettings.Issuer,
            //    Audience = _jwtSettings.Audience,// Audience Token的作用对象，也就是被访问的资源服务器授权标识
            //    Subject = new ClaimsIdentity(claim),
            //    NotBefore = DateTime.Now, //Token生效时间，在此之前不可用
            //    Expires = DateTime.Now.AddMinutes(30), //Token过期时间，在此之后不可用
            //    SigningCredentials = creds,
            //    IssuedAt = DateTime.Now //Token颁发时间
            //};
            
            
            
            //var handler = new JwtSecurityTokenHandler();
            //JwtSecurityToken token1 = handler.CreateJwtSecurityToken(descriptor);
            
            
            
            return Ok(new
            {
                token = new JwtSecurityTokenHandler().WriteToken(token)
            });

            //return Ok(new
            //{
            //    token = new JwtSecurityTokenHandler().WriteToken(token),
            //    token1 = handler.WriteToken(token1)
            //});
            //return Ok("登录成功!");
        }


        /// <summary>
        /// 登录处理
        /// </summary>
        /// <param name="uName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [AllowAnonymous]//跳过验证，加上该标签就可以在登陆验证时跳过该方法，一般加在登陆页上
        [HttpGet][HttpPost]
        public async Task<JsonResult> LoginProject(string uName, string password)
        {
            try
            {
                if (string.IsNullOrEmpty(uName) || string.IsNullOrEmpty(password))
                {
                    return Json(new { result = false, msg = "请完善信息后登录" });
                }
                //string strSql = "select * from t_user where userName=@userName and password =@password";
                //DataTable dt = DBHelper.GetDataTable(strSql, new MySqlParameter("@userName", uName), new MySqlParameter("@password", password));
                userInfo user = new userInfo();
                user.id = 1;
                user.name = "admin";
                user.pwd = "123456";
                if (user != null)
                {
                    #region 登录认证，存入Cookie
                    //登录认证，存入Cookie
                    var claims = new List<Claim>(){
                                  new Claim(ClaimTypes.Name,user.name),new Claim("password",user.pwd),new Claim("ID",user.id.ToString())
                               };
                    //init the identity instances 
                    var userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
                    //signin 
                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
                    {
                        ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
                        IsPersistent = false,
                        AllowRefresh = false
                    });
                    #endregion
                    return Json(new { result = true, userName = user.name, password = user.pwd, ID = user.id});
                }
                else
                {
                    return Json(new { result = false, msg = "用户名或密码输入错误，请重新输入" });
                }
            }
            catch (Exception ex)
            {
                return Json(new { result = false, msg = "登录失败" + ex.Message });
            }
        }


        /// <summary>
        /// 实现登出
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<JsonResult> Logout()
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return Json(new { msg = "退出成功" });
        }


        public class userInfo
        {
            public int id { get; set; }
            public string name { get; set; }
            public string pwd { get; set; }
        }

    }
}